package org.six11.olive3.server;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.six11.olive3.*;
import org.six11.olive3.net.Message;
import org.six11.olive3.net.MessageNames;
import org.six11.olive3.util.MiscFunctions;
import org.six11.util2.Debug;

/**
 * This class acts as a data warehouse for multi-client sketches. It is capable of receiving input
 * from any number of sources. It also will give clients data they need (and no more).
 * 
 * @author Gabe Johnson <johnsogg@cmu.edu>
 * 
 */
public class OliveRuntimeData {

  public enum Route {
    ALL_NO_ECHO, // everybody except originating user 
    ALL;         // everybody (including originating user)
  }

  List<Message> messages;
  Map<String, Route> routes;

  public OliveRuntimeData() {
    messages = new ArrayList<Message>();
    routes = new HashMap<String, Route>();
  }

  public void recordMessage(Message m) {
    synchronized (messages) {
      messages.add(m);
      messages.notifyAll();
    }
  }

  public void setRouting(String messageType, Route route) {
    routes.put(messageType, route);
  }

  public void retrieveData(String userID, int lastIndex, PrintWriter out) {
    synchronized (messages) {
      if (lastIndex >= (messages.size() - 1)) {
        try {
          messages.wait(5000);
        } catch (InterruptedException ex) {
          ex.printStackTrace();
        }
      }
    }
    int currentSize = messages.size();
    int tmpNumDownloaded = 0;
    for (int i = lastIndex; i < currentSize; i++) {
      tmpNumDownloaded = tmpNumDownloaded + routeWhenAppropriate(messages.get(i), userID, out);

    }
    out.write(MessageNames.MSG_LAST_MSG_IDX + " ( " + MessageNames.PARAM_MESSAGE_INDEX + "="
        + currentSize + ") { }\n\n");
  }

  private int routeWhenAppropriate(Message m, String userID, PrintWriter out) {
    int ret = 0;
    if (routes.containsKey(m.name)) {
      Route route = routes.get(m.name);
      switch (route) {
        case ALL:
          out.write(m.toOliveString());
          ret = 1;
          break;
        case ALL_NO_ECHO:
          if (!m.getParamValue(MessageNames.PARAM_USER_ID).equals(userID)) {
            out.write(m.toOliveString());
            ret = 1;
          }
          break;
      }
    }
    return ret;
  }
}